package com.horizon.common.interceptor;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 请求日志记录拦截器
 *
 * @author wangfuwei
 * @version 2018-08-13
 */
@Slf4j
public class LogInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        JSONObject logger = new JSONObject();
        //请求时间
        logger.put("requestTime", System.currentTimeMillis());
        //获取请求sessionId
        logger.put("sessionId", request.getRequestedSessionId() == null ? "" : request.getRequestedSessionId());
        //请求路径
        logger.put("url", request.getRequestURL());
        //设置客户端ip
        logger.put("ip", getCliectIp(request));
        //设置请求方法
        logger.put("method", request.getMethod());
        //设置请求类型（json|普通请求）
        logger.put("type", request.getHeader("X-Requested-With") == null ? "" : request.getHeader("X-Requested-With"));
        //浏览器
        logger.put("userAgent", request.getHeader("User-Agent"));
        //获取请求参数信息
        String paramData = JSON.toJSONString(request.getParameterMap(),
                SerializerFeature.WriteNullListAsEmpty,
                SerializerFeature.WriteNullStringAsEmpty,
                SerializerFeature.WriteNullBooleanAsFalse,
                SerializerFeature.WriteMapNullValue,
                SerializerFeature.DisableCircularReferenceDetect);
        logger.put("requestData", paramData);

        //设置请求实体到request内，方面afterCompletion方法调用
        request.setAttribute("__logger__", logger);
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        //获取本次请求日志实体
        JSONObject logger = (JSONObject) request.getAttribute("__logger__");
        //设置返回时间
        logger.put("returnTime", System.currentTimeMillis());
        //获取请求错误码
        logger.put("status", response.getStatus());
        //错误信息
        if (ex != null) {
            logger.put("msg", ex.getMessage() == null ? "" : ex.getMessage());
        }
        log.info(logger.toJSONString(), ex);
    }

    /**
     * 获取客户端ip地址
     *
     * @param request
     * @return
     */
    private String getCliectIp(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }

        if (!StringUtils.isEmpty(ip)) {
            // 多个路由时，取第一个非unknown的ip
            final String[] arr = ip.split(",");
            for (final String str : arr) {
                if (!"unknown".equalsIgnoreCase(str)) {
                    ip = str;
                    break;
                }
            }
        }
        return ip;
    }
}
